/*****************************************************************************
 * Copyright (C) Stacy Curl. All rights reserved.                            *
 * ------------------------------------------------------------------------- *
 * The software in this package is published under the terms of the BSD      *
 * style license a copy of which has been included with this distribution in *
 * the LICENSE.txt file.                                                     *
 *****************************************************************************/
package picounit.features.test_finder;

import picounit.Test;
import picounit.features.test_factory.TestFactory;
import picounit.util.ClassMarker;
import previous.picounit.Verify;

public class SinglePicoUnitTestSuiteTest implements previous.picounit.Test {
	private final Verify verify;
	private final previous.picounit.Should should;

	private TestFactory testFactory;

	interface NonTestInterface extends Test {}
	
	public SinglePicoUnitTestSuiteTest(previous.picounit.Should should, Verify verify) {
		this.should = should;
		this.verify = verify;
	}
	
	public void mock(TestFactory testFactory) {
		this.testFactory = testFactory;
	}

	public void testThrowsExceptionIfConstructedWithInterface() {
		expectIllegalArgumentException(NonTestInterface.class, " is an interface");
	}

	public void testThrowsExceptionIfConstructedWithAnAbstractClass() {
		abstract class NonTestClass implements Test {}

		expectIllegalArgumentException(NonTestClass.class, " is abstract");
	}

	public void testAddsTestErrorIfNoTestClassesAreFound() {
		class ExampleTest implements Test {}
		
		should.expectAboveWhenTheFollowingOccurs();
		
		SinglePicoUnitTestSuite singlePicoUnitTestSuite = singlePicoUnitTestSuite(ExampleTest.class);

		verify.that(singlePicoUnitTestSuite.countTestCases()).isEqualTo(1);
		verify.that(singlePicoUnitTestSuite.tests().nextElement())
			.isEqualTo(new NoTestsFoundTestCase(ExampleTest.class, new ClassMarker(Test.class)));
	}

	public void testTwoInstancesWithSameStartingClassAreEqual() {
		class StartingClass implements Test {}
		
		should.expectAboveWhenTheFollowingOccurs();

		verify.that(singlePicoUnitTestSuite(StartingClass.class))
			.isEqualTo(singlePicoUnitTestSuite(StartingClass.class));
	}

	public void testTwoInstancesWithSameStartingClassAndNameAreEqual() {
		class StartingClass implements Test {}

		should.expectAboveWhenTheFollowingOccurs();

		verify.that(singlePicoUnitTestSuite("name", StartingClass.class))
			.isEqualTo(singlePicoUnitTestSuite("name", StartingClass.class));
	}

	public void testTwoInstancesWithSameStartingClassButDifferentNameAreNotEqual() {
		class StartingClass implements Test {}

		should.expectAboveWhenTheFollowingOccurs();

		verify.that(singlePicoUnitTestSuite("different name", StartingClass.class))
			.isDifferentTo(singlePicoUnitTestSuite("name", StartingClass.class));
	}

	public void testHasSameNameAsTestClass() {
		class StartingClass implements Test {}

		should.expectAboveWhenTheFollowingOccurs();

		verify.that(singlePicoUnitTestSuite(StartingClass.class).getName())
			.isEqualTo(StartingClass.class.getName());
	}

	private void expectIllegalArgumentException(Class testClass, String expectedMessage) {
		try {
			singlePicoUnitTestSuite(testClass);

			verify.fail("IllegalArgumentException expected");
		}
		catch (IllegalArgumentException illegalArgumentException) {
			verify.that(illegalArgumentException.getMessage())
				.isEqualTo(testClass.getName() + expectedMessage);
		}
	}
	
	private SinglePicoUnitTestSuite singlePicoUnitTestSuite(Class startingClass) {
		return singlePicoUnitTestSuite(startingClass.getName(), startingClass);
	}

	private SinglePicoUnitTestSuite singlePicoUnitTestSuite(String name, Class startingClass) {
		return new SinglePicoUnitTestSuite(name, startingClass, testFactory);
	}
}
